package edu.langnan.xiaoli.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import edu.langnan.xiaoli.config.security.LoginUser;
import edu.langnan.xiaoli.config.security.TokenService;
import edu.langnan.xiaoli.core.domain.StudentDO;
import edu.langnan.xiaoli.core.dto.LoginBodyDTO;
import edu.langnan.xiaoli.core.dto.LoginInfoDTO;
import edu.langnan.xiaoli.core.dto.StudentDTO;
import edu.langnan.xiaoli.core.dto.WeiXinLoginResultDTO;
import edu.langnan.xiaoli.exception.CustomException;
import edu.langnan.xiaoli.exception.user.StudentNoExitException;
import edu.langnan.xiaoli.exception.user.UserPasswordNotMatchException;
import edu.langnan.xiaoli.mapper.StudentMapper;
import edu.langnan.xiaoli.service.StudentService;
import edu.langnan.xiaoli.service.TaskService;
import edu.langnan.xiaoli.service.WeiXinService;
import edu.langnan.xiaoli.utils.SecurityUtils;
import edu.langnan.xiaoli.utils.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Date;
import java.util.Set;

/**
 * @author cql
 */
@Service
public class StudentServiceImpl implements StudentService {

    private static final Logger log = LoggerFactory.getLogger(StudentService.class);

    @Autowired
    private TaskService taskService;

    @Autowired
    private StudentMapper studentMapper;

    @Autowired
    private PermissionService permissionService;

    @Resource
    private AuthenticationManager authenticationManager;

    @Autowired
    private TokenService tokenService;

    @Autowired
    private WeiXinService weiXinService;

    @Override
    public StudentDO findStudentByStuNo(String stuNo) {
        QueryWrapper<StudentDO> wrapper = new QueryWrapper<>();
        wrapper.eq("stu_no", stuNo);
        return studentMapper.selectOne(wrapper);
    }

    @Override
    public LoginInfoDTO login(LoginBodyDTO loginBody) {
        StudentDO student = this.findStudentByStuNo(loginBody.getStuNo());

        Date now = new Date();

        if (StringUtils.isNull(student)) {
            log.info("学号{}不存在", loginBody.getStuNo());
            throw new StudentNoExitException();
        }
        if (!SecurityUtils.matchesPassword(loginBody.getPassword(), student.getPassword())) {
            log.info("学号{}登录失败,密码不正确", loginBody.getStuNo());
            throw new UserPasswordNotMatchException();
        }


        // 用户验证
        Authentication authentication = null;
        try {
            authentication = authenticationManager
                    .authenticate(new UsernamePasswordAuthenticationToken(loginBody.getStuNo(), loginBody.getPassword()));
        } catch (Exception e) {
            log.error("出现异常: {}", e);
            if (e instanceof BadCredentialsException) {
                throw new UserPasswordNotMatchException();
            } else {
                throw new CustomException(e.getMessage());
            }
        }

        LoginUser loginUser = (LoginUser) authentication.getPrincipal();

        /**
         * TODO 微信登录，有没有优化的空间
         */
        // if (student.getOpenId() == null || student.getOpenId() != "") {
        //     WeiXinLoginResultDTO weiXinLogin = weiXinService.weiXinLogin(loginBody.getCode());
        //     if (weiXinLogin == null && StringUtils.isEmpty(weiXinLogin.getOpenid())) {
        //         throw new CustomException(weiXinLogin.getErrmsg());
        //     }
        //     loginUser.setOpenId(weiXinLogin.getOpenid());
        //     loginUser.setSessionKey(weiXinLogin.getSession_key());
        // }

        // 异步更新用户基本信息
        taskService.updateStudentInfo(student.getId(), loginBody.getAvatar(), loginUser.getOpenId(),now);


        // 生成 token
        String token = tokenService.createToken(loginUser);
        LoginInfoDTO result = new LoginInfoDTO(token, loginUser.getOpenId());
        return result;
    }

    @Override
    public StudentDTO findStuInfo(LoginUser loginUser) {
        // 1.基本信息
        StudentDTO studentDTO = studentMapper.findStuInfo(loginUser.getStuNo());
        if (StringUtils.isNull(studentDTO)) {
            throw new StudentNoExitException();
        }

        // 2.角色信息
        Set<String> roles = permissionService.getRoleOfStudent(loginUser.getId());
        studentDTO.setRoles(roles);

        // 3.权限信息
        Set<String> perms = permissionService.getPermOfStudent(loginUser.getId());
        studentDTO.setPerms(perms);


        return studentDTO;
    }

    @Override
    public void updateInfo(Integer stuId, String avatar, String openId, Date now) {
        studentMapper.updateInfo(stuId, avatar, openId, now);
    }
}
